package com.realtyManage.springboot.Controller;

import com.realtyManage.springboot.Model.Do.SpecialOfferHouse;
import com.realtyManage.springboot.Service.ISpecialOfferHouseService;
import com.realtyManage.springboot.Utils.AppletPayUtil;
import com.realtyManage.springboot.Config.WxProgramPayConfig;
import com.realtyManage.springboot.Model.Vo.RechargeVo;
import com.realtyManage.springboot.wxpay.PayUtil;
import com.realtyManage.springboot.wxpay.WXPayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

/**
 * 杭州素色网络科技有限公司
 * 2019.08.08
 * 微信支付
 */

@Controller
@RequestMapping("/wx")
public class WxPayController {

    @Autowired
    StringRedisTemplate template;

    @Autowired
    private ISpecialOfferHouseService specialOfferHouseService;

    /**
     * 成功的标识
     */
    private final static String SUCCESS="SUCCESS";

    /**
     * 返回状态码的变量名
     *
     */
    private final static String RETURN_CODE="RETURN_CODE";

    @RequestMapping(value = "/wxPay", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> wxPay(@RequestBody RechargeVo rechargeVo, HttpServletRequest request) {
        Map<String, Object> response = new HashMap<String, Object>();//返回给小程序端需要的参数
        synchronized(this) {
            SpecialOfferHouse so = specialOfferHouseService.getIdAllOne(Integer.valueOf(rechargeVo.getSuperHouseId()));
            if (so.getId() == null) {
                response.put("message", "房源已经预约！");
                return response;
            }
        }
            try {
                //获取code
                String code = rechargeVo.getCode();
                //调用接口获取openId
                String openid = AppletPayUtil.getOpenIdByCode(code);
                //生成的随机字符串
                String nonce_str = WXPayUtil.generateNonceStr();
                String out_trade_no = WXPayUtil.generateNonceStr();
                //获取支付金额
                String totalFee = rechargeVo.getRechargeMoney().toString();
                //商品名称
                String body = "带看费";
                //获取客户端的ip地址
                InetAddress addr = null;
                try {
                    addr = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                String spbill_create_ip = addr.getHostAddress();

                //组装参数，用户生成统一下单接口的签名
                Map<String, String> packageParams = new HashMap<String, String>();
                packageParams.put("appid", WxProgramPayConfig.APPID);
                packageParams.put("mch_id", WxProgramPayConfig.MCH_ID);
                packageParams.put("nonce_str", nonce_str);
                packageParams.put("body", body);
                packageParams.put("out_trade_no", out_trade_no);//商户订单号
                packageParams.put("total_fee", totalFee);//支付金额，这边需要转成字符串类型，否则后面的签名会失败
                packageParams.put("spbill_create_ip", spbill_create_ip);
                packageParams.put("notify_url", WxProgramPayConfig.NOTIFY_URL);//支付成功后的回调地址
                packageParams.put("trade_type", "JSAPI");//支付方式
                packageParams.put("openid", openid);

                String prestr = PayUtil.createLinkString(packageParams); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

                //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
                String mysign = PayUtil.sign(prestr, WxProgramPayConfig.KEY, "utf-8").toUpperCase();

                //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
                String xml = "<xml>" + "<appid>" + WxProgramPayConfig.APPID + "</appid>"
                        + "<body><![CDATA[" + body + "]]></body>"
                        + "<mch_id>" + WxProgramPayConfig.MCH_ID + "</mch_id>"
                        + "<nonce_str>" + nonce_str + "</nonce_str>"
                        + "<notify_url>" + WxProgramPayConfig.NOTIFY_URL + "</notify_url>"
                        + "<openid>" + openid + "</openid>"
                        + "<out_trade_no>" + out_trade_no + "</out_trade_no>"
                        + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
                        + "<total_fee>" + totalFee + "</total_fee>"
                        + "<trade_type>" + "JSAPI" + "</trade_type>"
                        + "<sign>" + mysign + "</sign>"
                        + "</xml>";

                System.out.println("调试模式_统一下单接口 请求XML数据：" + xml);

                //，并接受返回的结果
                String result = PayUtil.httpRequest(WxProgramPayConfig.pay_url, "POST", xml);

                System.out.println("调试模式_统一下单接口 返回XML数据：" + result);

                // 将解析结果存储在HashMap中
                Map map = PayUtil.doXMLParse(result);

                String return_code = (String) map.get("return_code");//返回状态码

                if (return_code.equals("SUCCESS")) {
                    String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                    response.put("nonceStr", nonce_str);
                    response.put("package", "prepay_id=" + prepay_id);
                    Long timeStamp = System.currentTimeMillis() / 1000;
                    response.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                    //拼接签名需要的参数
                    String stringSignTemp = "appId=" + WxProgramPayConfig.APPID + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                    //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                    String paySign = PayUtil.sign(stringSignTemp, WxProgramPayConfig.KEY, "utf-8").toUpperCase();
                    response.put("paySign", paySign);
                }
                response.put("appid", WxProgramPayConfig.APPID);
                return response;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
    }

}
